package cn.harry.cabinet.api

import android.content.Context
import android.util.Log
import cn.harry.cabinet.api.dto.ExternalApiRequest
import cn.harry.cabinet.api.dto.ExternalApiResponse
import cn.harry.cabinet.api.enums.ExternalServiceType
import cn.harry.cabinet.repository.ConfigurationRepository
import cn.harry.cabinet.utils.AppConfigKeys
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.util.concurrent.TimeUnit

/**
 * 外部接口客户端
 * 用于调用外部API接口
 */
class ExternalApiClient(context: Context) {
    
    private val configRepository = ConfigurationRepository(context.applicationContext as android.app.Application)
    
    companion object {
        const val TAG = "ExternalApiClient"
        
        @Volatile
        private var instance: ExternalApiClient? = null
        
        /**
         * 获取单例实例
         */
        fun getInstance(context: Context): ExternalApiClient {
            return instance ?: synchronized(this) {
                instance ?: ExternalApiClient(context.applicationContext).also {
                    instance = it
                }
            }
        }
    }
    
    val json = Json {
        ignoreUnknownKeys = true
        prettyPrint = false
        encodeDefaults = true
    }
    
    val client = OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build()
    
    /**
     * 检查外部接口是否启用
     */
    suspend fun isEnabled(): Boolean {
        return withContext(Dispatchers.IO) {
            val config = configRepository.getByTypeAndKey(
                AppConfigKeys.TYPE_NETWORK,
                AppConfigKeys.KEY_NETWORK_EXTERNAL_API_ENABLED
            )
            config?.value?.toBoolean() ?: false
        }
    }
    
    /**
     * 获取外部接口URL
     */
    suspend fun getApiUrl(): String? {
        return withContext(Dispatchers.IO) {
            configRepository.getByTypeAndKey(
                AppConfigKeys.TYPE_NETWORK,
                AppConfigKeys.KEY_NETWORK_EXTERNAL_API_URL
            )?.value
        }
    }
    
    /**
     * 获取访问令牌
     */
    suspend fun getToken(): String? {
        return withContext(Dispatchers.IO) {
            configRepository.getByTypeAndKey(
                AppConfigKeys.TYPE_NETWORK,
                AppConfigKeys.KEY_NETWORK_TOKEN
            )?.value
        }
    }
    
    /**
     * 获取设备编号
     */
    suspend fun getDeviceNo(): String {
        return withContext(Dispatchers.IO) {
            configRepository.getByTypeAndKey(
                AppConfigKeys.TYPE_HOME,
                AppConfigKeys.KEY_HOME_DEVICE_NUMBER
            )?.value ?: "default"
        }
    }
    
    /**
     * 发送请求到外部接口
     * @param serviceType 服务类型
     * @param bodyData 请求体数据
     * @return 响应结果
     */
    @OptIn(InternalSerializationApi::class)
    suspend inline fun <reified T, reified R> sendRequest(
        serviceType: ExternalServiceType,
        bodyData: T
    ): Result<ExternalApiResponse<R>> {
        return withContext(Dispatchers.IO) {
            try {
                // 检查是否启用
                if (!isEnabled()) {
                    Log.e(TAG, "外部接口未启用，跳过请求: ${serviceType.serviceName}")
                    return@withContext Result.success(
                        ExternalApiResponse<R>(
                            code = -1,
                            message = "外部接口未启用",
                            success = false
                        )
                    )
                }
                
                // 获取配置
                val apiUrl = getApiUrl()
                if (apiUrl.isNullOrBlank()) {
                    Log.w(TAG, "外部接口地址未配置")
                    return@withContext Result.failure(
                        Exception("外部接口地址未配置")
                    )
                }
                
                val deviceNo = getDeviceNo()
                val token = getToken()
                
                Log.d(TAG, "准备发送请求: ${serviceType.serviceName}, URL: $apiUrl, 设备号: $deviceNo")
                
                // 构建请求
                val request = ExternalApiRequest.create(deviceNo, serviceType, bodyData)
                val requestJson = json.encodeToString(
                    ExternalApiRequest.serializer(serializer<T>()),
                    request
                )
                
                Log.d(TAG, "请求内容: $requestJson")
                
                // 构建HTTP请求
                val requestBuilder = Request.Builder()
                    .url(apiUrl)
                    .post(requestJson.toRequestBody("application/json".toMediaType()))
                
                // 添加Token
                if (!token.isNullOrBlank()) {
                    requestBuilder.addHeader("Authorization", token)
                    Log.d(TAG, "已添加Token认证")
                }
                
                val httpRequest = requestBuilder.build()
                
                // 发送请求
                val response = client.newCall(httpRequest).execute()
                
                Log.d(TAG, "收到响应: HTTP ${response.code}")
                
                if (!response.isSuccessful) {
                    return@withContext Result.failure(
                        Exception("HTTP请求失败: ${response.code}")
                    )
                }
                
                val responseBody = response.body?.string()
                if (responseBody.isNullOrBlank()) {
                    Log.w(TAG, "响应体为空")
                    return@withContext Result.failure(
                        Exception("响应体为空")
                    )
                }
                
                Log.d(TAG, "响应内容: $responseBody")
                
                // 解析响应
                val apiResponse = json.decodeFromString<ExternalApiResponse<R>>(responseBody)
                
                if (apiResponse.success) {
                    Log.d(TAG, "请求成功: ${apiResponse.message}")
                } else {
                    Log.w(TAG, "请求失败: ${apiResponse.message}")
                }
                
                Result.success(apiResponse)
                
            } catch (e: Exception) {
                Log.e(TAG, "请求异常: ${e.message}", e)
                Result.failure(e)
            }
        }
    }
    
    /**
     * 发送空请求体的请求
     */
    @OptIn(InternalSerializationApi::class)
    suspend inline fun <reified R> sendEmptyRequest(
        serviceType: ExternalServiceType
    ): Result<ExternalApiResponse<R>> {
        return sendRequest<String, R>(serviceType, "")
    }

}
